﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Xml.Linq;

namespace devtm.Editor.TypeSelector.AttributeBuilder
{
    public class AttributeMap : INotifyPropertyChanged
    {

        public AttributeMap(ContextAttributeBuilderElement parent)
        {
            Parent = parent;
            Root = parent.Root;
            Constructors = new ObservableCollection<Constructor>();
            Constructors.CollectionChanged += Constructors_CollectionChanged;
        }       

        #region Properties

        public ContextAttributeBuilderElement Parent { get; set; }
        public ContextAttributeBuilder Root { get; set; }

        private Type _attributeSelected;
        public Type AttributeSelected
        {
            get { return _attributeSelected; }
            set
            {

                _attributeSelected = value;
                MyPropertyChanged("AttributeSelected");

                Constructors.Clear();

                foreach (ConstructorInfo item in _attributeSelected.GetConstructors())
                    Constructors.Add(new Constructor(this, item));

                if (Constructors.Count == 1)
                    this.Parent.ExpandSubtree();


                foreach (Constructor item in Constructors)
                {
                    item.ExpandSubtree();
                    break;
                }

            }
        }

        public ObservableCollection<Constructor> Constructors { get; set; }

        void Constructors_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {

            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
            {
                foreach (var item in e.NewItems)
                    Parent.Items.Add(item);
            }
            else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
            {
                foreach (var item in e.OldItems)
                    Parent.Items.Remove(item);
            }
            else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset)
                Parent.Items.Clear();
        }

        #endregion

        #region INotifyPropertyChanged

        protected void MyPropertyChanged(PropertyChangedEventArgs e)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, e);
        }

        protected void MyPropertyChanged(string propertyName)
        {
            MyPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        internal void ConstructorChecked(Constructor constructor)
        {

            constructor.ExpandSubtree();
            foreach (Constructor item in Constructors)
                if (item != constructor)
                    item.IsExpanded = false;
        }

        #region In/Out

        private const string nodeName = "attribute";
        public XElement Serialize()
        {

            XElement ret = 
                new XElement(
                    nodeName, 
                    new XAttribute("type", AttributeSelected.AssemblyQualifiedName)
                    );

            foreach (Constructor item in Constructors)
                if (item.IsExpanded)
                    ret.Add(item.Serialize());

            return ret;

        }

        internal void UnSerialize(XElement node)
        {

            if (node.Name.LocalName != nodeName)
                return;

            string typeName = (string)node.Attribute("type");
            Type type = Type.GetType(typeName);

            if (type == null)
                throw new Exception(string.Format("{0} can't be resolved, make sure the library has referenced", typeName));

            AttributeSelected = type;

            XElement node2 = node.Element("ctr");
            string sign = (string)node2.Attribute("sgn");

            foreach (Constructor constructor in Constructors)
            {
                if (constructor.Title == sign)
                {
                    constructor.IsExpanded = true;
                    constructor.UnSerialize(node2);
                    break;
                }
            }

            // find constructor



        }

        #endregion

    }

}